package org.lwx.reflect.method;

import org.lwx.annotation.target.AliasFor;
import org.lwx.annotation.target.METHOD;
import org.lwx.reflect.pojo.User;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 通过class获取类的方法
 */
public class getMethodTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class<User> aClass = (Class<User>) Class.forName("org.lwx.reflect.pojo.User");
        Constructor<User> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        User user = declaredConstructor.newInstance();
        /*
         * 测试method相关的,一共有4个
         * getMethod只能获取public的方法
         */
        // 获取一个没有输入的方法
        Method publicMethod = aClass.getMethod("publicMethod");
        if (publicMethod.isAnnotationPresent(METHOD.class)) {
            METHOD method = publicMethod.getAnnotation(METHOD.class);
            Annotation[] annotations = METHOD.class.getDeclaredAnnotations();
            Constructor<?>[] declaredConstructors = METHOD.class.getDeclaredConstructors();
            Field[] declaredFields = METHOD.class.getDeclaredFields();
            Method[] declaredMethods = METHOD.class.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                if (declaredMethod.isAnnotationPresent(AliasFor.class)) {
                    AliasFor declaredAnnotation = declaredMethod.getDeclaredAnnotation(AliasFor.class);
                    System.out.println(declaredAnnotation.value());
                }
            }
            System.out.println();
        }
        publicMethod.invoke(user);
        Method publicMethod1 = aClass.getMethod("publicMethod", String.class);
//        boolean annotationPresent1 = publicMethod1.isAnnotationPresent(METHOD.class);
        publicMethod1.invoke(user, "Hello,publicMethod");

        //

        /*
            getDeclaredMethod可以获取任意修饰符修饰的对象
        */
        Method privateMethod = aClass.getDeclaredMethod("privateMethod");
        // 通过反射调用私有方法前需要先设置为可访问,否则会抛出IllegalAccessException
        privateMethod.setAccessible(true);
        privateMethod.invoke(user);
        Method privateMethod1 = aClass.getDeclaredMethod("privateMethod", String.class);
        privateMethod1.setAccessible(true);
        privateMethod1.invoke(user, "hello, privateMethod ");


        /*
            获取所有public方法(包括继承自父类的方法)
         */
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            // 这样写肯定是不行的了,除非全部都是无参构造函数
//            method.invoke(user);
        }

        /*
        *   获取所有方法(不包括继承自父类的方法)
        *   从字面上也可以看出,就仅仅只是返回定义在该类上的方法
        */
        Method[] declaredMethods = aClass.getDeclaredMethods();


        // 这个方法与局部和内部类相关,用的应该是不多的
        Method enclosingMethod = aClass.getEnclosingMethod();

        Runnable runnable = new Runnable() {
            @Override
            public void run() {

            }
        };
        Method enclosingMethod1 = runnable.getClass().getEnclosingMethod();

        System.out.println();
    }
}
